package cn.pink.common.support.utils;


public class DataCron {

	/* ==================== 每日重置相关 ==================== */

//	/** 每日零时重置 */
	public static final String CRON_DAY_ZERO = "0 0 0 * * ?";
	public static final String SUB_DAY_ZERO = "0000";

	/** 每日4时重置 */
//	public static final String CRON_DAY_4ST = "0 0 4 * * ?";
//	public static final String SUB_DAY_4ST = "0400";

	/** 每日4时1分重置 */
//	public static final String CRON_DAY_4ST_1MIN = "0 1 4 * * ?";
//	public static final String SUB_DAY_4ST_1MIN = "0410";
	
	/** 每日5时重置 */
//	public static final String CRON_DAY_5ST = "0 0 5 * * ?";
//	public static final String SUB_DAY_5ST = "0500";

//	/** 每日12时重置 */
//	public static final String CRON_DAY_12ST = "0 0 12 * * ?";
//	public static final String SUB_DAY_12ST = "1200";

//	/** 每日18时重置 */
//	public static final String CRON_DAY_18ST = "0 0 18 * * ?";
//	public static final String SUB_DAY_18ST = "1800";

//	/** 每日21时重置 */
//	public static final String CRON_DAY_21ST = "0 0 21 * * ?";
//	public static final String SUB_DAY_21ST = "2100";

	/** 每日默认重置配置*/
	public static final String CRON_DAY_DEFAULT = CRON_DAY_ZERO;
	public static final String SUB_DAY_DEFAULT = SUB_DAY_ZERO;

	/* ==================== 每周重置相关 ==================== */

//	/** 每周一0点重置 */
	public static final String CRON_WEEK_ZERO = "0 0 0 ? * 2";
	public static final String SUB_WEEK_ZERO = "10000";
//
//	/** 每周一4时重置 */
//	public static final String CRON_WEEK_4ST = "0 0 4 ? * 2";
//	public static final String SUB_WEEK_4ST = "10400";

	/** 每周五4时重置 */
//	public static final String CRON_WEEK_FIVE_4ST = "0 0 4 ? * 6";
//	public static final String SUB_WEEK_FIVE_4ST = "104006";

	/** 每周默认重置配置 */
	public static final String CRON_WEEK_DEFAULT = CRON_WEEK_ZERO;
	public static final String SUB_WEEK_DEFAULT = SUB_WEEK_ZERO;

	/* ==================== 每月重置相关 ==================== */

	/** 每月1日0时重置 */
	public static final String CRON_MONTH_ZERO = "0 0 0 1 1/1 ?";
	public static final String SUB_MONTH_ZERO = "1000";

	/** 每月1日4时重置 */
//	public static final String CRON_MONTH_4ST = "0 0 4 1 1/1 ?";
//	public static final String SUB_MONTH_4ST = "1040";

	/** 每月默认重置配置 (当前配置为每月1日4时重置) */
	public static final String CRON_MONTH_DEFAULT = CRON_MONTH_ZERO;
	public static final String SUB_MONTH_DEFAULT = SUB_MONTH_ZERO;

	/* ==================== 每年重置相关（暂时只支持在1月份重置） ==================== */
	
	/** 每年1月1日0时重置 */
	public static final String CRON_YEAR_ZERO = "0 0 0 1 1 ? *";
	public static final String SUB_YEAR_ZERO = "10011";

	/** 每年1月1日4时重置 */
//	public static final String CRON_YEAR_4ST = "0 0 4 1 1 ? *";
//	public static final String SUB_YEAR_4ST = "10411";

	/** 每月默认重置配置 (当前配置为年1月1日4时重置) */
	public static final String CRON_YEAR_DEFAULT = CRON_YEAR_ZERO;
	public static final String SUB_YEAR_DEFAULT = SUB_YEAR_ZERO;

	/* ==================== 自由重置相关 ==================== */

	/** 自由一日，每15分钟开启一次 */
	public static final String CRON_FREE_DAY = "0 0/15 * * * ?";

	/* ==================== 重置时间解析相关 ==================== */

	/** 每日重置时间相对于零点的偏移量 */
	public static long dayResetTimeOffsetFromZero;

	/** 每周重置时间相对于零点的偏移量 */
	public static long weekResetTimeOffsetFromZero;

	/** 每月重置时间相对于零点的偏移量 */
	public static long monthResetTimeOffsetFromZero;

	/** 每年重置时间相对于零点的偏移量 */
	public static long yearResetTimeOffsetFromZero;


	static {
		String[] parsedResetDay = CRON_DAY_DEFAULT.split(" ");
		String[] parsedResetWeek = CRON_WEEK_DEFAULT.split(" ");
		String[] parsedResetMonth = CRON_MONTH_DEFAULT.split(" ");
		String[] parsedResetYear = CRON_YEAR_DEFAULT.split(" ");

		dayResetTimeOffsetFromZero = getHourInCron(parsedResetDay) * TimeUtils.HOUR +
				getMinuteInCron(parsedResetDay) * TimeUtils.MIN +
				getSecondInCron(parsedResetDay) * TimeUtils.SEC;

		weekResetTimeOffsetFromZero = getDayOfWeekOffsetInCron(parsedResetWeek) * TimeUtils.DAY +
				getHourInCron(parsedResetWeek) * TimeUtils.HOUR +
				getMinuteInCron(parsedResetWeek) * TimeUtils.MIN +
				getSecondInCron(parsedResetWeek) * TimeUtils.SEC;

		monthResetTimeOffsetFromZero = getDayOfMonthOffsetInCron(parsedResetMonth) * TimeUtils.DAY +
				getHourInCron(parsedResetMonth) * TimeUtils.HOUR +
				getMinuteInCron(parsedResetMonth) * TimeUtils.MIN +
				getSecondInCron(parsedResetMonth) * TimeUtils.SEC;

		yearResetTimeOffsetFromZero = getDayOfMonthOffsetInCron(parsedResetYear) * TimeUtils.DAY +
				getHourInCron(parsedResetYear) * TimeUtils.HOUR +
				getMinuteInCron(parsedResetYear) * TimeUtils.MIN +
				getSecondInCron(parsedResetYear) * TimeUtils.SEC;
	}


	/**
	 * 获取CRON表达式的”秒钟”字段
	 * @param cron
	 * @return
	 */
	public static int getSecondInCron(String[] cron) {
		try {
			return Integer.parseInt(cron[0]);
		} catch (NumberFormatException e) {
			return 0;
		}
	}

	/**
	 * 获取CRON表达式的”分钟”字段
	 * @param cron
	 * @return
	 */
	public static int getMinuteInCron(String[] cron) {
		try {
			return Integer.parseInt(cron[1]);
		} catch (NumberFormatException e) {
			return 0;
		}
	}

	/**
	 * 获取CRON表达式的”时钟”字段
	 * @param cron
	 * @return
	 */
	public static int getHourInCron(String[] cron) {
		try {
			return Integer.parseInt(cron[2]);
		} catch (NumberFormatException e) {
			return 0;
		}
	}

	/**
	 * 获取CRON表达式的”每月X号”字段相对于”每月1号”的偏移
	 * @param cron
	 * @return
	 */
	public static int getDayOfMonthOffsetInCron(String[] cron) {
		try {
			return Integer.parseInt(cron[3]) - 1;
		} catch (NumberFormatException e) {
			return 1;
		}
	}

	/**
	 * 获取CRON表达式的”星期X”字段相对于”星期一”的偏移（星期日为-1）
	 * @param cron
	 * @return
	 */
	public static int getDayOfWeekOffsetInCron(String[] cron) {
		try {
			return Integer.parseInt(cron[5]) - 2;
		} catch (NumberFormatException e) {
			return 0;
		}
	}

	/**
	 * 获得指定时间戳的当日重置时间
	 * @param timeNow
	 * @return
	 */
	public static long getResetTimeOfDay(long timeNow) {
		long resetTime = TimeUtils.getZeroOfDay(timeNow) + dayResetTimeOffsetFromZero;
		return resetTime > timeNow ? resetTime - TimeUtils.DAY : resetTime;
	}

	/**
	 * 获取指定时间戳对应【星期重置日】的零点
	 * @param timeNow
	 * @return
	 */
	public static long getResetTimeOfWeek(long timeNow) {
		long resetTime = TimeUtils.getMondayZeroOfWeek(timeNow) + weekResetTimeOffsetFromZero;
		return resetTime > timeNow ? resetTime - 7 * TimeUtils.DAY : resetTime;
	}

	/**
	 * 获取指定时间戳对应【月重置日】的零点
	 * @param timeNow
	 * @return
	 */
	public static long getResetTimeOfMonth(long timeNow) {
		long resetTime = TimeUtils.getFirstDayZeroOfMonth(timeNow) + monthResetTimeOffsetFromZero;
		return resetTime > timeNow ? TimeUtils.getLastFirstDayTimeOfMonth(timeNow) : resetTime;
	}

	/**
	 * 获取指定时间戳对应【年重置日】的零点（假定年重置日肯定在一月）
	 * @param timeNow
	 * @return
	 */
	public static long getResetTimeOfYear(long timeNow) {
		long resetTime = TimeUtils.getFirstDayTimeOfYear(timeNow) + yearResetTimeOffsetFromZero;
		return resetTime > timeNow ? TimeUtils.getLastFirstDayTimeOfYear(timeNow) : resetTime;
	}

	/**
	 * 获取【当前时间】与【起始时间】之间的【游戏日】间隔天数
	 * @param startTime
	 * @param timeNow
	 * @return
	 */
	public static int getDaysBetween(long startTime, long timeNow) {
		long resetTimeOfStartDay = getResetTimeOfDay(startTime);
		long resetTimeOfCurrDay = getResetTimeOfDay(timeNow);
		return (int)((resetTimeOfCurrDay - resetTimeOfStartDay) / TimeUtils.DAY);
	}

	/**
	 * 判断两个时间是否在同一个游戏日
	 * @param prevTime
	 * @param timeNow
	 * @return
	 */
	public static boolean isSameDay(long prevTime, long timeNow) {
		return TimeUtils.isSameDay(getResetTimeOfDay(prevTime), getResetTimeOfDay(timeNow));
	}
}
